home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / avgdvg.c < prev    next >
C/C++ Source or Header  |  2000-05-13  |  28KB  |  1,159 lines

  1. /*
  2.  * avgdvg.c: Atari DVG and AVG simulators
  3.  *
  4.  * Copyright 1991, 1992, 1996 Eric Smith
  5.  *
  6.  * Modified for the MAME project 1997 by
  7.  * Brad Oliver, Bernd Wiebelt, Aaron Giles, Andrew Caldwell
  8.  *
  9.  * 971108 Disabled vector timing routines, introduced an ugly (but fast!)
  10.  *        busy flag hack instead. BW
  11.  * 980202 New anti aliasing code by Andrew Caldwell (.ac)
  12.  * 980206 New (cleaner) busy flag handling.
  13.  *        Moved LBO's buffered point into generic vector code. BW
  14.  * 980212 Introduced timing code based on Aaron timer routines. BW
  15.  * 980318 Better color handling, Bzone and MHavoc clipping. BW
  16.  *
  17.  * Battlezone uses a red overlay for the top of the screen and a green one
  18.  * for the rest. There is a circuit to clip color 0 lines extending to the
  19.  * red zone. This is emulated now. Thanks to Neil Bradley for the info. BW
  20.  *
  21.  * Frame and interrupt rates (Neil Bradley) BW
  22.  * ~60 fps/4.0ms: Asteroid, Asteroid Deluxe
  23.  * ~40 fps/4.0ms: Lunar Lander
  24.  * ~40 fps/4.1ms: Battle Zone
  25.  * ~45 fps/5.4ms: Space Duel, Red Baron
  26.  * ~30 fps/5.4ms: StarWars
  27.  *
  28.  * Games with self adjusting framerate
  29.  *
  30.  * 4.1ms: Black Widow, Gravitar
  31.  * 4.1ms: Tempest
  32.  * Major Havoc
  33.  * Quantum
  34.  *
  35.  * TODO: accurate vector timing (need timing diagramm)
  36.  */
  37.  
  38. #include "driver.h"
  39. #include "avgdvg.h"
  40. #include "vector.h"
  41.  
  42. #define VEC_SHIFT 16    /* fixed for the moment */
  43. #define BRIGHTNESS 12   /* for maximum brightness, use 16! */
  44.  
  45.  
  46. /* the screen is red above this Y coordinate */
  47. #define BZONE_TOP 0x0050
  48. #define BZONE_CLIP \
  49.     vector_add_clip (xmin<<VEC_SHIFT, BZONE_TOP<<VEC_SHIFT, \
  50.                     xmax<<VEC_SHIFT, ymax<<VEC_SHIFT)
  51. #define BZONE_NOCLIP \
  52.     vector_add_clip (xmin<<VEC_SHIFT, ymin <<VEC_SHIFT, \
  53.                     xmax<<VEC_SHIFT, ymax<<VEC_SHIFT)
  54.  
  55. #define MHAVOC_YWINDOW 0x0048
  56. #define MHAVOC_CLIP \
  57.     vector_add_clip (xmin<<VEC_SHIFT, MHAVOC_YWINDOW<<VEC_SHIFT, \
  58.                     xmax<<VEC_SHIFT, ymax<<VEC_SHIFT)
  59. #define MHAVOC_NOCLIP \
  60.     vector_add_clip (xmin<<VEC_SHIFT, ymin <<VEC_SHIFT, \
  61.                     xmax<<VEC_SHIFT, ymax<<VEC_SHIFT)
  62.  
  63. static int vectorEngine = USE_DVG;
  64. static int flipword = 0; /* little/big endian issues */
  65. static int busy = 0;     /* vector engine busy? */
  66. static int colorram[16]; /* colorram entries */
  67.  
  68. /* These hold the X/Y coordinates the vector engine uses */
  69. static int width; int height;
  70. static int xcenter; int ycenter;
  71. static int xmin; int xmax;
  72. static int ymin; int ymax;
  73.  
  74.  
  75. int vector_updates; /* avgdvg_go_w()'s per Mame frame, should be 1 */
  76.  
  77. static int vg_step = 0;    /* single step the vector generator */
  78. static int total_length;   /* length of all lines drawn in a frame */
  79.  
  80. #define MAXSTACK 8     /* Tempest needs more than 4     BW 210797 */
  81.  
  82. /* AVG commands */
  83. #define VCTR 0
  84. #define HALT 1
  85. #define SVEC 2
  86. #define STAT 3
  87. #define CNTR 4
  88. #define JSRL 5
  89. #define RTSL 6
  90. #define JMPL 7
  91. #define SCAL 8
  92.  
  93. /* DVG commands */
  94. #define DVCTR 0x01
  95. #define DLABS 0x0a
  96. #define DHALT 0x0b
  97. #define DJSRL 0x0c
  98. #define DRTSL 0x0d
  99. #define DJMPL 0x0e
  100. #define DSVEC 0x0f
  101.  
  102. #define twos_comp_val(num,bits) ((num&(1<<(bits-1)))?(num|~((1<<bits)-1)):(num&((1<<bits)-1)))
  103.  
  104. char *avg_mnem[] = { "vctr", "halt", "svec", "stat", "cntr",
  105.              "jsrl", "rtsl", "jmpl", "scal" };
  106.  
  107. char *dvg_mnem[] = { "????", "vct1", "vct2", "vct3",
  108.              "vct4", "vct5", "vct6", "vct7",
  109.              "vct8", "vct9", "labs", "halt",
  110.              "jsrl", "rtsl", "jmpl", "svec" };
  111.  
  112. /* ASG 971210 -- added banks and modified the read macros to use them */
  113. #define BANK_BITS 13
  114. #define BANK_SIZE (1<<BANK_BITS)
  115. #define NUM_BANKS (0x4000/BANK_SIZE)
  116. #define VECTORRAM(offset) (vectorbank[(offset)>>BANK_BITS][(offset)&(BANK_SIZE-1)])
  117. static unsigned char *vectorbank[NUM_BANKS];
  118.  
  119. #define map_addr(n) (((n)<<1))
  120. #define memrdwd(offset) (VECTORRAM(offset) | (VECTORRAM(offset+1)<<8))
  121. /* The AVG used by Star Wars reads the bytes in the opposite order */
  122. #define memrdwd_flip(offset) (VECTORRAM(offset+1) | (VECTORRAM(offset)<<8))
  123. #define max(x,y) (((x)>(y))?(x):(y))
  124.  
  125.  
  126. INLINE void vector_timer (int deltax, int deltay)
  127. {
  128.     deltax = abs (deltax);
  129.     deltay = abs (deltay);
  130.     total_length += max (deltax, deltay) >> VEC_SHIFT;
  131. }
  132.  
  133. INLINE void dvg_vector_timer (int scale)
  134. {
  135.     total_length += scale;
  136. }
  137.  
  138. static void dvg_generate_vector_list(void)
  139. {
  140.     int pc;
  141.     int sp;
  142.     int stack [MAXSTACK];
  143.  
  144.     int scale;
  145.     int statz;
  146.  
  147.     int currentx, currenty;
  148.  
  149.     int done = 0;
  150.  
  151.     int firstwd;
  152.     int secondwd = 0; /* Initialize to tease the compiler */
  153.     int opcode;
  154.  
  155.     int x, y;
  156.     int z, temp;
  157.     int a;
  158.  
  159.     int deltax, deltay;
  160.  
  161.     vector_clear_list();
  162.     pc = 0;
  163.     sp = 0;
  164.     scale = 0;
  165.     statz = 0;
  166.  
  167.     currentx = 0;
  168.     currenty = 0;
  169.  
  170.     while (!done)
  171.     {
  172.  
  173. #ifdef VG_DEBUG
  174.         if (vg_step)
  175.         {
  176.               logerror("Current beam position: (%d, %d)\n",
  177.                 currentx, currenty);
  178.               getchar();
  179.         }
  180. #endif
  181.  
  182.         firstwd = memrdwd (map_addr (pc));
  183.         opcode = firstwd >> 12;
  184. #ifdef VG_DEBUG
  185.         logerror("%4x: %4x ", map_addr (pc), firstwd);
  186. #endif
  187.         pc++;
  188.         if ((opcode >= 0 /* DVCTR */) && (opcode <= DLABS))
  189.         {
  190.             secondwd = memrdwd (map_addr (pc));
  191.             pc++;
  192. #ifdef VG_DEBUG
  193.             logerror("%s ", dvg_mnem [opcode]);
  194.             logerror("%4x  ", secondwd);
  195. #endif
  196.         }
  197. #ifdef VG_DEBUG
  198.         else logerror("Illegal opcode ");
  199. #endif
  200.  
  201.         switch (opcode)
  202.         {
  203.             case 0:
  204. #ifdef VG_DEBUG
  205.                  logerror("Error: DVG opcode 0!  Addr %4x Instr %4x %4x\n", map_addr (pc-2), firstwd, secondwd);
  206.                 done = 1;
  207.                 break;
  208. #endif
  209.             case 1:
  210.             case 2:
  211.             case 3:
  212.             case 4:
  213.             case 5:
  214.             case 6:
  215.             case 7:
  216.             case 8:
  217.             case 9:
  218.                   y = firstwd & 0x03ff;
  219.                 if (firstwd & 0x400)
  220.                     y=-y;
  221.                 x = secondwd & 0x3ff;
  222.                 if (secondwd & 0x400)
  223.                     x=-x;
  224.                 z = secondwd >> 12;
  225. #ifdef VG_DEBUG
  226.                 logerror("(%d,%d) z: %d scal: %d", x, y, z, opcode);
  227. #endif
  228.                   temp = ((scale + opcode) & 0x0f);
  229.                   if (temp > 9)
  230.                     temp = -1;
  231.                   deltax = (x << VEC_SHIFT) >> (9-temp);        /* ASG 080497 */
  232.                 deltay = (y << VEC_SHIFT) >> (9-temp);        /* ASG 080497 */
  233.                   currentx += deltax;
  234.                 currenty -= deltay;
  235.                 dvg_vector_timer(temp);
  236.  
  237.                 /* ASG 080497, .ac JAN2498 - V.V */
  238.                 if (translucency)
  239.                     z = z * BRIGHTNESS;
  240.                 else
  241.                     if (z) z = (z << 4) | 0x0f;
  242.                 vector_add_point (currentx, currenty, colorram[1], z);
  243.  
  244.                 break;
  245.  
  246.             case DLABS:
  247.                 x = twos_comp_val (secondwd, 12);
  248.                 y = twos_comp_val (firstwd, 12);
  249.                   scale = (secondwd >> 12);
  250.                 currentx = ((x-xmin) << VEC_SHIFT);        /* ASG 080497 */
  251.                 currenty = ((ymax-y) << VEC_SHIFT);        /* ASG 080497 */
  252. #ifdef VG_DEBUG
  253.                 logerror("(%d,%d) scal: %d", x, y, secondwd >> 12);
  254. #endif
  255.                 break;
  256.  
  257.             case DHALT:
  258. #ifdef VG_DEBUG
  259.                 if ((firstwd & 0x0fff) != 0)
  260.                       logerror("(%d?)", firstwd & 0x0fff);
  261. #endif
  262.                 done = 1;
  263.                 break;
  264.  
  265.             case DJSRL:
  266.                 a = firstwd & 0x0fff;
  267. #ifdef VG_DEBUG
  268.                 logerror("%4x", map_addr(a));
  269. #endif
  270.                 stack [sp] = pc;
  271.                 if (sp == (MAXSTACK - 1))
  272.                     {
  273.                     logerror("\n*** Vector generator stack overflow! ***\n");
  274.                     done = 1;
  275.                     sp = 0;
  276.                 }
  277.                 else
  278.                     sp++;
  279.                 pc = a;
  280.                 break;
  281.  
  282.             case DRTSL:
  283. #ifdef VG_DEBUG
  284.                 if ((firstwd & 0x0fff) != 0)
  285.                      logerror("(%d?)", firstwd & 0x0fff);
  286. #endif
  287.                 if (sp == 0)
  288.                     {
  289.                     logerror("\n*** Vector generator stack underflow! ***\n");
  290.                     done = 1;
  291.                     sp = MAXSTACK - 1;
  292.                 }
  293.                 else
  294.                     sp--;
  295.                 pc = stack [sp];
  296.                 break;
  297.  
  298.             case DJMPL:
  299.                 a = firstwd & 0x0fff;
  300. #ifdef VG_DEBUG
  301.                 logerror("%4x", map_addr(a));
  302. #endif
  303.                 pc = a;
  304.                 break;
  305.  
  306.             case DSVEC:
  307.                 y = firstwd & 0x0300;
  308.                 if (firstwd & 0x0400)
  309.                     y = -y;
  310.                 x = (firstwd & 0x03) << 8;
  311.                 if (firstwd & 0x04)
  312.                     x = -x;
  313.                 z = (firstwd >> 4) & 0x0f;
  314.                 temp = 2 + ((firstwd >> 2) & 0x02) + ((firstwd >>11) & 0x01);
  315.                   temp = ((scale + temp) & 0x0f);
  316.                 if (temp > 9)
  317.                     temp = -1;
  318. #ifdef VG_DEBUG
  319.                 logerror("(%d,%d) z: %d scal: %d", x, y, z, temp);
  320. #endif
  321.  
  322.                 deltax = (x << VEC_SHIFT) >> (9-temp);    /* ASG 080497 */
  323.                 deltay = (y << VEC_SHIFT) >> (9-temp);    /* ASG 080497 */
  324.                   currentx += deltax;
  325.                 currenty -= deltay;
  326.                 dvg_vector_timer(temp);
  327.  
  328.                 /* ASG 080497, .ac JAN2498 */
  329.                 if (translucency)
  330.                     z = z * BRIGHTNESS;
  331.                 else
  332.                     if (z) z = (z << 4) | 0x0f;
  333.                 vector_add_point (currentx, currenty, colorram[1], z);
  334.                 break;
  335.  
  336.             default:
  337.                 logerror("Unknown DVG opcode found\n");
  338.                 done = 1;
  339.         }
  340. #ifdef VG_DEBUG
  341.               logerror("\n");
  342. #endif
  343.     }
  344. }
  345.  
  346. /*
  347. Atari Analog Vector Generator Instruction Set
  348.  
  349. Compiled from Atari schematics and specifications
  350. Eric Smith  7/2/92
  351. ---------------------------------------------
  352.  
  353. NOTE: The vector generator is little-endian.  The instructions are 16 bit
  354.       words, which need to be stored with the least significant byte in the
  355.       lower (even) address.  They are shown here with the MSB on the left.
  356.  
  357. The stack allows four levels of subroutine calls in the TTL version, but only
  358. three levels in the gate array version.
  359.  
  360. inst  bit pattern          description
  361. ----  -------------------  -------------------
  362. VCTR  000- yyyy yyyy yyyy  normal vector
  363.       zzz- xxxx xxxx xxxx
  364. HALT  001- ---- ---- ----  halt - does CNTR also on newer hardware
  365. SVEC  010y yyyy zzzx xxxx  short vector - don't use zero length
  366. STAT  0110 ---- zzzz cccc  status
  367. SCAL  0111 -bbb llll llll  scaling
  368. CNTR  100- ---- dddd dddd  center
  369. JSRL  101a aaaa aaaa aaaa  jump to subroutine
  370. RTSL  110- ---- ---- ----  return
  371. JMPL  111a aaaa aaaa aaaa  jump
  372.  
  373. -     unused bits
  374. x, y  relative x and y coordinates in two's complement (5 or 13 bit,
  375.       5 bit quantities are scaled by 2, so x=1 is really a length 2 vector.
  376. z     intensity, 0 = blank, 1 means use z from STAT instruction,  2-7 are
  377.       doubled for actual range of 4-14
  378. c     color
  379. b     binary scaling, multiplies all lengths by 2**(1-b), 0 is double size,
  380.       1 is normal, 2 is half, 3 is 1/4, etc.
  381. l     linear scaling, multiplies all lengths by 1-l/256, don't exceed $80
  382. d     delay time, use $40
  383. a     address (word address relative to base of vector memory)
  384.  
  385. Notes:
  386.  
  387. Quantum:
  388.         the VCTR instruction has a four bit Z field, that is not
  389.         doubled.  The value 2 means use Z from STAT instruction.
  390.  
  391.         the SVEC instruction can't be used
  392.  
  393. Major Havoc:
  394.         SCAL bit 11 is used for setting a Y axis window.
  395.  
  396.         STAT bit 11 is used to enable "sparkle" color.
  397.         STAT bit 10 inverts the X axis of vectors.
  398.         STAT bits 9 and 8 are the Vector ROM bank select.
  399.  
  400. Star Wars:
  401.         STAT bits 10, 9, and 8 are used directly for R, G, and B.
  402. */
  403.  
  404. static void avg_generate_vector_list (void)
  405. {
  406.  
  407.     int pc;
  408.     int sp;
  409.     int stack [MAXSTACK];
  410.  
  411.     int scale;
  412.     int statz   = 0;
  413.     int sparkle = 0;
  414.     int xflip   = 0;
  415.  
  416.     int color   = 0;
  417.     int bz_col  = -1; /* Battle Zone color selection */
  418.     int ywindow = -1; /* Major Havoc Y-Window */
  419.  
  420.     int currentx, currenty;
  421.     int done    = 0;
  422.  
  423.     int firstwd, secondwd;
  424.     int opcode;
  425.  
  426.     int x, y, z=0, b, l, d, a;
  427.  
  428.     int deltax, deltay;
  429.  
  430.  
  431.     pc = 0;
  432.     sp = 0;
  433.     statz = 0;
  434.     color = 0;
  435.  
  436.     if (flipword)
  437.     {
  438.         firstwd = memrdwd_flip (map_addr (pc));
  439.         secondwd = memrdwd_flip (map_addr (pc+1));
  440.     }
  441.     else
  442.     {
  443.         firstwd = memrdwd (map_addr (pc));
  444.         secondwd = memrdwd (map_addr (pc+1));
  445.     }
  446.     if ((firstwd == 0) && (secondwd == 0))
  447.     {
  448.         logerror("VGO with zeroed vector memory\n");
  449.         return;
  450.     }
  451.  
  452.     /* kludge to bypass Major Havoc's empty frames. BW 980216 */
  453.     if (vectorEngine == USE_AVG_MHAVOC && firstwd == 0xafe2)
  454.         return;
  455.  
  456.     scale = 0;          /* ASG 080497 */
  457.     currentx = xcenter; /* ASG 080497 */ /*.ac JAN2498 */
  458.     currenty = ycenter; /* ASG 080497 */ /*.ac JAN2498 */
  459.  
  460.     vector_clear_list();
  461.  
  462.     while (!done)
  463.     {
  464.  
  465. #ifdef VG_DEBUG
  466.         if (vg_step) getchar();
  467. #endif
  468.  
  469.         if (flipword) firstwd = memrdwd_flip (map_addr (pc));
  470.         else          firstwd = memrdwd      (map_addr (pc));
  471.  
  472.         opcode = firstwd >> 13;
  473. #ifdef VG_DEBUG
  474.         logerror("%4x: %4x ", map_addr (pc), firstwd);
  475. #endif
  476.         pc++;
  477.         if (opcode == VCTR)
  478.         {
  479.             if (flipword) secondwd = memrdwd_flip (map_addr (pc));
  480.             else          secondwd = memrdwd      (map_addr (pc));
  481.             pc++;
  482. #ifdef VG_DEBUG
  483.             logerror("%4x  ", secondwd);
  484. #endif
  485.         }
  486. #ifdef VG_DEBUG
  487.         else logerror("      ");
  488. #endif
  489.  
  490.         if ((opcode == STAT) && ((firstwd & 0x1000) != 0))
  491.             opcode = SCAL;
  492.  
  493. #ifdef VG_DEBUG
  494.         logerror("%s ", avg_mnem [opcode]);
  495. #endif
  496.  
  497.         switch (opcode)
  498.         {
  499.             case VCTR:
  500.  
  501.                 if (vectorEngine == USE_AVG_QUANTUM)
  502.                 {
  503.                     x = twos_comp_val (secondwd, 12);
  504.                     y = twos_comp_val (firstwd, 12);
  505.                 }
  506.                 else
  507.                 {
  508.                     /* These work for all other games. */
  509.                     x = twos_comp_val (secondwd, 13);
  510.                     y = twos_comp_val (firstwd, 13);
  511.                 }
  512.                 z = (secondwd >> 12) & ~0x01;
  513.  
  514.                 /* z is the maximum DAC output, and      */
  515.                 /* the 8 bit value from STAT does some   */
  516.                 /* fine tuning. STATs of 128 should give */
  517.                 /* highest intensity. */
  518.                 if (vectorEngine == USE_AVG_SWARS)
  519.                 {
  520.                     if (translucency)
  521.                         z = (statz * z) / 12;
  522.                     else
  523.                         z = (statz * z) >> 3;
  524.                     if (z > 0xff)
  525.                         z = 0xff;
  526.                 }
  527.                 else
  528.                 {
  529.                     if (z == 2)
  530.                         z = statz;
  531.                         if (translucency)
  532.                             z = z * BRIGHTNESS;
  533.                         else
  534.                             if (z) z = (z << 4) | 0x1f;
  535.                 }
  536.  
  537.                 deltax = x * scale;
  538.                 if (xflip) deltax = -deltax;
  539.  
  540.                 deltay = y * scale;
  541.                 currentx += deltax;
  542.                 currenty -= deltay;
  543.                 vector_timer(deltax, deltay);
  544.  
  545.                 if (sparkle)
  546.                 {
  547.                     color = rand() & 0x07;
  548.                 }
  549.  
  550.                 if ((vectorEngine == USE_AVG_BZONE) && (bz_col != 0))
  551.                 {
  552.                     if (currenty < (BZONE_TOP<<16))
  553.                         color = 4;
  554.                     else
  555.                         color = 2;
  556.                 }
  557.  
  558.                 vector_add_point (currentx, currenty, colorram[color], z);
  559.  
  560. #ifdef VG_DEBUG
  561.                 logerror("VCTR x:%d y:%d z:%d statz:%d", x, y, z, statz);
  562. #endif
  563.                 break;
  564.  
  565.             case SVEC:
  566.                 x = twos_comp_val (firstwd, 5) << 1;
  567.                 y = twos_comp_val (firstwd >> 8, 5) << 1;
  568.                 z = ((firstwd >> 4) & 0x0e);
  569.  
  570.                 if (vectorEngine == USE_AVG_SWARS)
  571.                 {
  572.                     if (translucency)
  573.                         z = (statz * z) / 12;
  574.                     else
  575.                         z = (statz * z) >> 3;
  576.                     if (z > 0xff) z = 0xff;
  577.                 }
  578.                 else
  579.                 {
  580.                     if (z == 2)
  581.                         z = statz;
  582.                         if (translucency)
  583.                             z = z * BRIGHTNESS;
  584.                         else
  585.                             if (z) z = (z << 4) | 0x1f;
  586.                 }
  587.  
  588.                 deltax = x * scale;
  589.                 if (xflip) deltax = -deltax;
  590.  
  591.                 deltay = y * scale;
  592.                 currentx += deltax;
  593.                 currenty -= deltay;
  594.                 vector_timer(deltax, deltay);
  595.  
  596.                 if (sparkle)
  597.                 {
  598.                     color = rand() & 0x07;
  599.                 }
  600.  
  601.                 vector_add_point (currentx, currenty, colorram[color], z);
  602.  
  603. #ifdef VG_DEBUG
  604.                 logerror("SVEC x:%d y:%d z:%d statz:%d", x, y, z, statz);
  605. #endif
  606.                 break;
  607.  
  608.             case STAT:
  609.                 if (vectorEngine == USE_AVG_SWARS)
  610.                 {
  611.                     /* color code 0-7 stored in top 3 bits of `color' */
  612.                     color=(char)((firstwd & 0x0700)>>8);
  613.                     statz = (firstwd) & 0xff;
  614.                 }
  615.                 else
  616.                 {
  617.                     color = (firstwd) & 0x000f;
  618.                     statz = (firstwd >> 4) & 0x000f;
  619.                     if (vectorEngine == USE_AVG_TEMPEST)
  620.                                 sparkle = !(firstwd & 0x0800);
  621.                     if (vectorEngine == USE_AVG_MHAVOC)
  622.                     {
  623.                         sparkle = (firstwd & 0x0800);
  624.                         xflip = firstwd & 0x0400;
  625.                         /* Bank switch the vector ROM for Major Havoc */
  626.                         vectorbank[1] = &memory_region(REGION_CPU1)[0x18000 + ((firstwd & 0x300) >> 8) * 0x2000];
  627.                     }
  628.                     if (vectorEngine == USE_AVG_BZONE)
  629.                     {
  630.                         bz_col = color;
  631.                         if (color == 0)
  632.                         {
  633.                             BZONE_CLIP;
  634.                             color = 2;
  635.                         }
  636.                         else
  637.                         {
  638.                             BZONE_NOCLIP;
  639.                         }
  640.                     }
  641.                 }
  642. #ifdef VG_DEBUG
  643.                 logerror("STAT: statz: %d color: %d", statz, color);
  644.                 if (xflip || sparkle)
  645.                     logerror("xflip: %02x  sparkle: %02x\n", xflip, sparkle);
  646. #endif
  647.  
  648.                 break;
  649.  
  650.             case SCAL:
  651.                 b = ((firstwd >> 8) & 0x07)+8;
  652.                 l = (~firstwd) & 0xff;
  653.                 scale = (l << VEC_SHIFT) >> b;        /* ASG 080497 */
  654.  
  655.                 /* Y-Window toggle for Major Havoc BW 980318 */
  656.                 if (vectorEngine == USE_AVG_MHAVOC)
  657.                 {
  658.                     if (firstwd & 0x0800)
  659.                     {
  660.                         logerror("CLIP %d\n", firstwd & 0x0800);
  661.                         if (ywindow == 0)
  662.                         {
  663.                             ywindow = 1;
  664.                             MHAVOC_CLIP;
  665.                         }
  666.                         else
  667.                         {
  668.                             ywindow = 0;
  669.                             MHAVOC_NOCLIP;
  670.                         }
  671.                     }
  672.                 }
  673. #ifdef VG_DEBUG
  674.                 logerror("bin: %d, lin: ", b);
  675.                 if (l > 0x80)
  676.                     logerror("(%d?)", l);
  677.                 else
  678.                     logerror("%d", l);
  679.                 logerror(" scale: %f", (scale/(float)(1<<VEC_SHIFT)));
  680. #endif
  681.                 break;
  682.  
  683.             case CNTR:
  684.                 d = firstwd & 0xff;
  685. #ifdef VG_DEBUG
  686.                 if (d != 0x40) logerror("%d", d);
  687. #endif
  688.                 currentx = xcenter ;  /* ASG 080497 */ /*.ac JAN2498 */
  689.                 currenty = ycenter ;  /* ASG 080497 */ /*.ac JAN2498 */
  690.                 vector_add_point (currentx, currenty, 0, 0);
  691.                 break;
  692.  
  693.             case RTSL:
  694. #ifdef VG_DEBUG
  695.                 if ((firstwd & 0x1fff) != 0)
  696.                     logerror("(%d?)", firstwd & 0x1fff);
  697. #endif
  698.                 if (sp == 0)
  699.                 {
  700.                     logerror("\n*** Vector generator stack underflow! ***\n");
  701.                     done = 1;
  702.                     sp = MAXSTACK - 1;
  703.                 }
  704.                 else
  705.                     sp--;
  706.  
  707.                 pc = stack [sp];
  708.                 break;
  709.  
  710.             case HALT:
  711. #ifdef VG_DEBUG
  712.                 if ((firstwd & 0x1fff) != 0)
  713.                     logerror("(%d?)", firstwd & 0x1fff);
  714. #endif
  715.                 done = 1;
  716.                 break;
  717.  
  718.             case JMPL:
  719.                 a = firstwd & 0x1fff;
  720. #ifdef VG_DEBUG
  721.                 logerror("%4x", map_addr(a));
  722. #endif
  723.                 /* if a = 0x0000, treat as HALT */
  724.                 if (a == 0x0000)
  725.                     done = 1;
  726.                 else
  727.                     pc = a;
  728.                 break;
  729.  
  730.             case JSRL:
  731.                 a = firstwd & 0x1fff;
  732. #ifdef VG_DEBUG
  733.                 logerror("%4x", map_addr(a));
  734. #endif
  735.                 /* if a = 0x0000, treat as HALT */
  736.                 if (a == 0x0000)
  737.                     done = 1;
  738.                 else
  739.                 {
  740.                     stack [sp] = pc;
  741.                     if (sp == (MAXSTACK - 1))
  742.                     {
  743.                         logerror("\n*** Vector generator stack overflow! ***\n");
  744.                         done = 1;
  745.                         sp = 0;
  746.                     }
  747.                     else
  748.                         sp++;
  749.  
  750.                     pc = a;
  751.                 }
  752.                 break;
  753.  
  754.             default:
  755.                 logerror("internal error\n");
  756.         }
  757. #ifdef VG_DEBUG
  758.         logerror("\n");
  759. #endif
  760.     }
  761. }
  762.  
  763.  
  764. int avgdvg_done (void)
  765. {
  766.     if (busy)
  767.         return 0;
  768.     else
  769.         return 1;
  770. }
  771.  
  772. static void avgdvg_clr_busy (int dummy)
  773. {
  774.     busy = 0;
  775. }
  776.  
  777. WRITE_HANDLER( avgdvg_go_w )
  778. {
  779.  
  780.     if (busy)
  781.         return;
  782.  
  783.     vector_updates++;
  784.     total_length = 1;
  785.     busy = 1;
  786.  
  787.     if (vectorEngine == USE_DVG)
  788.     {
  789.         dvg_generate_vector_list();
  790.         timer_set (TIME_IN_NSEC(4500) * total_length, 1, avgdvg_clr_busy);
  791.     }
  792.     else
  793.     {
  794.         avg_generate_vector_list();
  795.         if (total_length > 1)
  796.             timer_set (TIME_IN_NSEC(1500) * total_length, 1, avgdvg_clr_busy);
  797.         /* this is for Major Havoc */
  798.         else
  799.         {
  800.             vector_updates--;
  801.             busy = 0;
  802.         }
  803.     }
  804. }
  805.  
  806. WRITE_HANDLER( avgdvg_reset_w )
  807. {
  808.     avgdvg_clr_busy (0);
  809. }
  810.  
  811. int avgdvg_init (int vgType)
  812. {
  813.     int i;
  814.  
  815.     if (vectorram_size == 0)
  816.     {
  817.         logerror("Error: vectorram_size not initialized\n");
  818.         return 1;
  819.     }
  820.  
  821.     /* ASG 971210 -- initialize the pages */
  822.     for (i = 0; i < NUM_BANKS; i++)
  823.         vectorbank[i] = vectorram + (i<<BANK_BITS);
  824.     if (vgType == USE_AVG_MHAVOC)
  825.         vectorbank[1] = &memory_region(REGION_CPU1)[0x18000];
  826.  
  827.     vectorEngine = vgType;
  828.     if ((vectorEngine<AVGDVG_MIN) || (vectorEngine>AVGDVG_MAX))
  829.     {
  830.         logerror("Error: unknown Atari Vector Game Type\n");
  831.         return 1;
  832.     }
  833.  
  834.     if (vectorEngine==USE_AVG_SWARS)
  835.         flipword=1;
  836. #ifndef LSB_FIRST
  837.     else if (vectorEngine==USE_AVG_QUANTUM)
  838.         flipword=1;
  839. #endif
  840.     else
  841.         flipword=0;
  842.  
  843.     vg_step = 0;
  844.  
  845.     busy = 0;
  846.  
  847.     xmin=Machine->drv->visible_area.min_x;
  848.     ymin=Machine->drv->visible_area.min_y;
  849.     xmax=Machine->drv->visible_area.max_x;
  850.     ymax=Machine->drv->visible_area.max_y;
  851.     width=xmax-xmin;
  852.     height=ymax-ymin;
  853.  
  854.     xcenter=((xmax+xmin)/2) << VEC_SHIFT; /*.ac JAN2498 */
  855.     ycenter=((ymax+ymin)/2) << VEC_SHIFT; /*.ac JAN2498 */
  856.  
  857.     vector_set_shift (VEC_SHIFT);
  858.  
  859.     if (vector_vh_start())
  860.         return 1;
  861.  
  862.     return 0;
  863. }
  864.  
  865. /*
  866.  * These functions initialise the colors for all atari games.
  867.  */
  868.  
  869. #define RED   0x04
  870. #define GREEN 0x02
  871. #define BLUE  0x01
  872. #define WHITE RED|GREEN|BLUE
  873.  
  874. static void shade_fill (unsigned char *palette, int rgb, int start_index, int end_index, int start_inten, int end_inten)
  875. {
  876.     int i, inten, index_range, inten_range;
  877.  
  878.     index_range = end_index-start_index;
  879.     inten_range = end_inten-start_inten;
  880.     for (i = start_index; i <= end_index; i++)
  881.     {
  882.         inten = start_inten + (inten_range) * (i-start_index) / (index_range);
  883.         palette[3*i  ] = (rgb & RED  )? inten : 0;
  884.         palette[3*i+1] = (rgb & GREEN)? inten : 0;
  885.         palette[3*i+2] = (rgb & BLUE )? inten : 0;
  886.     }
  887. }
  888.  
  889. #define VEC_PAL_WHITE    1
  890. #define VEC_PAL_AQUA    2
  891. #define VEC_PAL_BZONE    3
  892. #define VEC_PAL_MULTI    4
  893. #define VEC_PAL_SWARS    5
  894. #define VEC_PAL_ASTDELUX    6
  895.  
  896. /* Helper function to construct the color palette for the Atari vector
  897.  * games. DO NOT reference this function from the Gamedriver or
  898.  * MachineDriver. Use "avg_init_palette_XXXXX" instead. */
  899. void avg_init_palette (int paltype, unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
  900. {
  901.     int i,j,k;
  902.  
  903.     int trcl1[] = { 0,0,2,2,1,1 };
  904.     int trcl2[] = { 1,2,0,1,0,2 };
  905.     int trcl3[] = { 2,1,1,0,2,0 };
  906.  
  907.     /* initialize the first 8 colors with the basic colors */
  908.     /* Only these are selected by writes to the colorram. */
  909.     for (i = 0; i < 8; i++)
  910.     {
  911.         palette[3*i  ] = (i & RED  ) ? 0xff : 0;
  912.         palette[3*i+1] = (i & GREEN) ? 0xff : 0;
  913.         palette[3*i+2] = (i & BLUE ) ? 0xff : 0;
  914.     }
  915.  
  916.     /* initialize the colorram */
  917.     for (i = 0; i < 16; i++)
  918.         colorram[i] = i & 0x07;
  919.  
  920.     /* fill the rest of the 256 color entries depending on the game */
  921.     switch (paltype)
  922.     {
  923.         /* Black and White vector colors (Asteroids,Omega Race) .ac JAN2498 */
  924.         case  VEC_PAL_WHITE:
  925.             shade_fill (palette, RED|GREEN|BLUE, 8, 128+8, 0, 255);
  926.             colorram[1] = 7; /* BW games use only color 1 (== white) */
  927.             break;
  928.  
  929.         /* Monochrome Aqua colors (Asteroids Deluxe,Red Baron) .ac JAN2498 */
  930.         case  VEC_PAL_ASTDELUX:
  931.             /* Use backdrop if present MLR OCT0598 */
  932.             backdrop_load("astdelux.png", 32, Machine->drv->total_colors-32);
  933.             if (artwork_backdrop!=NULL)
  934.             {
  935.                 shade_fill (palette, GREEN|BLUE, 8, 23, 1, 254);
  936.                 /* Some more anti-aliasing colors. */
  937.                 shade_fill (palette, GREEN|BLUE, 24, 31, 1, 254);
  938.                 for (i=0; i<8; i++)
  939.                     palette[(24+i)*3]=80;
  940.                 memcpy (palette+3*artwork_backdrop->start_pen, artwork_backdrop->orig_palette,
  941.                     3*artwork_backdrop->num_pens_used);
  942.             }
  943.             else
  944.                 shade_fill (palette, GREEN|BLUE, 8, 128+8, 1, 254);
  945.             colorram[1] =  3; /* for Asteroids */
  946.             break;
  947.  
  948.         case  VEC_PAL_AQUA:
  949.             shade_fill (palette, GREEN|BLUE, 8, 128+8, 1, 254);
  950.             colorram[0] =  3; /* for Red Baron */
  951.             break;
  952.  
  953.         /* Monochrome Green/Red vector colors (Battlezone) .ac JAN2498 */
  954.         case  VEC_PAL_BZONE:
  955.             shade_fill (palette, RED  ,  8, 23, 1, 254);
  956.             shade_fill (palette, GREEN, 24, 31, 1, 254);
  957.             shade_fill (palette, WHITE, 32, 47, 1, 254);
  958.             /* Use backdrop if present MLR OCT0598 */
  959.             backdrop_load("bzone.png", 48, Machine->drv->total_colors-48);
  960.             if (artwork_backdrop!=NULL)
  961.                 memcpy (palette+3*artwork_backdrop->start_pen, artwork_backdrop->orig_palette, 3*artwork_backdrop->num_pens_used);
  962.             break;
  963.  
  964.         /* Colored games (Major Havoc, Star Wars, Tempest) .ac JAN2498 */
  965.         case  VEC_PAL_MULTI:
  966.         case  VEC_PAL_SWARS:
  967.             /* put in 40 shades for red, blue and magenta */
  968.             shade_fill (palette, RED       ,   8,  47, 10, 250);
  969.             shade_fill (palette, BLUE      ,  48,  87, 10, 250);
  970.             shade_fill (palette, RED|BLUE  ,  88, 127, 10, 250);
  971.  
  972.             /* put in 20 shades for yellow and green */
  973.             shade_fill (palette, GREEN     , 128, 147, 10, 250);
  974.             shade_fill (palette, RED|GREEN , 148, 167, 10, 250);
  975.  
  976.             /* and 14 shades for cyan and white */
  977.             shade_fill (palette, BLUE|GREEN, 168, 181, 10, 250);
  978.             shade_fill (palette, WHITE     , 182, 194, 10, 250);
  979.  
  980.             /* Fill in unused gaps with more anti-aliasing colors. */
  981.             /* There are 60 slots available.           .ac JAN2498 */
  982.             i=195;
  983.             for (j=0; j<6; j++)
  984.             {
  985.                 for (k=7; k<=16; k++)
  986.                 {
  987.                     palette[3*i+trcl1[j]] = ((256*k)/16)-1;
  988.                     palette[3*i+trcl2[j]] = ((128*k)/16)-1;
  989.                     palette[3*i+trcl3[j]] = 0;
  990.                     i++;
  991.                 }
  992.             }
  993.             break;
  994.         default:
  995.             logerror("Wrong palette type in avgdvg.c");
  996.             break;
  997.     }
  998. }
  999.  
  1000. /* A macro for the palette_init functions */
  1001. #define VEC_PAL_INIT(name, paltype) \
  1002. void avg_init_palette_##name## (unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom) \
  1003. { avg_init_palette (##paltype##, palette, colortable, color_prom); }
  1004.  
  1005. /* The functions referenced from gamedriver */
  1006. VEC_PAL_INIT(white,    VEC_PAL_WHITE)
  1007. VEC_PAL_INIT(aqua ,    VEC_PAL_AQUA )
  1008. VEC_PAL_INIT(bzone,    VEC_PAL_BZONE)
  1009. VEC_PAL_INIT(multi,    VEC_PAL_MULTI)
  1010. VEC_PAL_INIT(swars,    VEC_PAL_SWARS)
  1011. VEC_PAL_INIT(astdelux, VEC_PAL_ASTDELUX )
  1012.  
  1013.  
  1014. /* If you want to use the next two functions, please make sure that you have
  1015.  * a fake GfxLayout, otherwise you'll crash */
  1016. static WRITE_HANDLER( colorram_w )
  1017. {
  1018.     colorram[offset & 0x0f] = data & 0x0f;
  1019. }
  1020.  
  1021. /*
  1022.  * Tempest, Major Havoc and Quantum select colors via a 16 byte colorram.
  1023.  * What's more, they have a different ordering of the rgbi bits than the other
  1024.  * color avg games.
  1025.  * We need translation tables.
  1026.  */
  1027.  
  1028. WRITE_HANDLER( tempest_colorram_w )
  1029. {
  1030. #if 0 /* with low intensity bit */
  1031.     int trans[]= { 7, 15, 3, 11, 6, 14, 2, 10, 5, 13, 1,  9, 4, 12, 0,  8 };
  1032. #else /* high intensity */
  1033.     int trans[]= { 7,  7, 3,  3, 6,  6, 2,  2, 5,  5, 1,  1, 4,  4, 0,  0 };
  1034. #endif
  1035.     colorram_w (offset, trans[data & 0x0f]);
  1036. }
  1037.  
  1038. WRITE_HANDLER( mhavoc_colorram_w )
  1039. {
  1040. #if 0 /* with low intensity bit */
  1041.     int trans[]= { 7, 6, 5, 4, 15, 14, 13, 12, 3, 2, 1, 0, 11, 10, 9, 8 };
  1042. #else /* high intensity */
  1043.     int trans[]= { 7, 6, 5, 4,  7,  6,  5,  4, 3, 2, 1, 0,  3,  2, 1, 0 };
  1044. #endif
  1045.     logerror("colorram: %02x: %02x\n", offset, data);
  1046.     colorram_w (offset , trans[data & 0x0f]);
  1047. }
  1048.  
  1049.  
  1050. WRITE_HANDLER( quantum_colorram_w )
  1051. {
  1052. /* Notes on colors:
  1053. offset:                color:            color (game):
  1054. 0 - score, some text        0 - black?
  1055. 1 - nothing?            1 - blue
  1056. 2 - nothing?            2 - green
  1057. 3 - Quantum, streaks        3 - cyan
  1058. 4 - text/part 1 player        4 - red
  1059. 5 - part 2 of player        5 - purple
  1060. 6 - nothing?            6 - yellow
  1061. 7 - part 3 of player        7 - white
  1062. 8 - stars            8 - black
  1063. 9 - nothing?            9 - blue
  1064. 10 - nothing?            10 - green
  1065. 11 - some text, 1up, like 3    11 - cyan
  1066. 12 - some text, like 4
  1067. 13 - nothing?            13 - purple
  1068. 14 - nothing?
  1069. 15 - nothing?
  1070.  
  1071. 1up should be blue
  1072. score should be red
  1073. high score - white? yellow?
  1074. level # - green
  1075. */
  1076.  
  1077.     int trans[]= { 7/*white*/, 0, 3, 1/*blue*/, 2/*green*/, 5, 6, 4/*red*/,
  1078.                7/*white*/, 0, 3, 1/*blue*/, 2/*green*/, 5, 6, 4/*red*/};
  1079.  
  1080.     colorram_w (offset >> 1, trans[data & 0x0f]);
  1081. }
  1082.  
  1083. /***************************************************************************
  1084.  
  1085.   Draw the game screen in the given osd_bitmap.
  1086.   Do NOT call osd_update_display() from this function, it will be called by
  1087.   the main emulation engine.
  1088.  
  1089. ***************************************************************************/
  1090.  
  1091. int dvg_start(void)
  1092. {
  1093.     if (artwork_backdrop)
  1094.     {
  1095.         backdrop_refresh(artwork_backdrop);
  1096.         backdrop_refresh_tables (artwork_backdrop);
  1097.     }
  1098.  
  1099.     return avgdvg_init (USE_DVG);
  1100. }
  1101.  
  1102. int avg_start(void)
  1103. {
  1104.     return avgdvg_init (USE_AVG);
  1105. }
  1106.  
  1107. int avg_start_starwars(void)
  1108. {
  1109.     return avgdvg_init (USE_AVG_SWARS);
  1110. }
  1111.  
  1112. int avg_start_tempest(void)
  1113. {
  1114.     return avgdvg_init (USE_AVG_TEMPEST);
  1115. }
  1116.  
  1117. int avg_start_mhavoc(void)
  1118. {
  1119.     return avgdvg_init (USE_AVG_MHAVOC);
  1120. }
  1121.  
  1122. int avg_start_bzone(void)
  1123. {
  1124.     if (artwork_backdrop)
  1125.     {
  1126.         backdrop_refresh(artwork_backdrop);
  1127.         backdrop_refresh_tables (artwork_backdrop);
  1128.     }
  1129.  
  1130.     return avgdvg_init (USE_AVG_BZONE);
  1131. }
  1132.  
  1133. int avg_start_quantum(void)
  1134. {
  1135.     return avgdvg_init (USE_AVG_QUANTUM);
  1136. }
  1137.  
  1138. int avg_start_redbaron(void)
  1139. {
  1140.     return avgdvg_init (USE_AVG_RBARON);
  1141. }
  1142.  
  1143. void avg_stop(void)
  1144. {
  1145.     busy = 0;
  1146.     vector_clear_list();
  1147.  
  1148.     vector_vh_stop();
  1149. }
  1150.  
  1151. void dvg_stop(void)
  1152. {
  1153.     busy = 0;
  1154.     vector_clear_list();
  1155.  
  1156.     vector_vh_stop();
  1157. }
  1158.  
  1159.